package edu.joe.game.solvers;

import edu.joe.game.ParticleData;
import edu.joe.game.ParticleMotionSolver;
import edu.joe.game.ParticlePhysicsModel;

/**
 * Gravity solver simulates gravity on particles, where each particle attracts
 * every other particle according to its mass and inverse distance.
 * 
 * @author Joe
 * 
 */
public class GravitySolver extends ParticleMotionSolver {

	public GravitySolver(ParticleData[] particles, ParticlePhysicsModel physics) {
		super(particles, physics);
	}

	@Override
	public void update(double dt) {
		for (int i = 0; i < super.particles.length; i++) {
			ParticleData particle = super.particles[i];
			if (particle.life > 0) {
				particle.life -= dt;
				particle.x += particle.dx * dt;
				particle.y += particle.dy * dt;
				particle.z += particle.dz * dt;

				particle.dx *= this.physics.velocityDamp;
				particle.dy *= this.physics.velocityDamp;
				particle.dz *= this.physics.velocityDamp;

				particle.dx += particle.fx * dt;
				particle.dy += particle.fy * dt + this.physics.gravity * dt;
				particle.dz += particle.fz * dt;

				particle.fx *= this.physics.velocityDamp;
				particle.fy *= this.physics.velocityDamp;
				particle.fz *= this.physics.velocityDamp;

				double m1 = particle.mass;

				if (physics.hitsFloor) {
					particle.dy *= -physics.bounceFactor;
				}
				for (int j = 0; j < super.particles.length; j++) {
					ParticleData particle2 = super.particles[j];
					if (particle2.life > 0) {
						double m2 = particle2.mass;
						double bx = particle2.x;
						double by = particle2.y;
						double bz = particle2.z;
						double dist = (bx - particle.x) * (bx - particle.x)
								+ (by - particle.y) * (by - particle.y)
								+ (bz - particle.z) * (bz - particle.z);
						double mag = 100.0;
						if (dist > 0.0000001) {
							mag = (0.01 * m2 * m1) / (dist * dist);
						}
						mag = mag > 100 ? 100 : mag;
						double mx = 0.01 * mag * (bx - particle.x);
						double my = 0.01 * mag * (by - particle.y);
						double mz = 0.01 * mag * (bz - particle.z);
						particle.fx += mx;
						particle.fy += my;
						particle.fz += mz;
					}
				}
			}
		}
	}
}
